package com.example.itemreader.restart;

import com.example.pojo.Customer;
import org.springframework.batch.item.*;
import org.springframework.batch.item.file.FlatFileItemReader;
import org.springframework.batch.item.file.mapping.DefaultLineMapper;
import org.springframework.batch.item.file.mapping.FieldSetMapper;
import org.springframework.batch.item.file.transform.DelimitedLineTokenizer;
import org.springframework.batch.item.file.transform.FieldSet;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Component;

/**
 * @author XieYa
 */
@Component("restartReader")
public class RestartReader implements ItemStreamReader<Customer> {
    // 读取文件使用
    private final FlatFileItemReader<Customer> customerFlatFileItemReader = new FlatFileItemReader<>();

    // 记录当前读取行数
    private Long curLine = 0L;

    // 是否重新读取
    private boolean restart = false;

    // 执行的上下文
    private ExecutionContext executionContext;

    public RestartReader() {
        customerFlatFileItemReader.setResource(new ClassPathResource("restart.txt"));
        // 跳过第一行
        customerFlatFileItemReader.setLinesToSkip(1);
        // 如何解析数据
        DelimitedLineTokenizer tokenizer = new DelimitedLineTokenizer();
        // 指定4个表头字段
        tokenizer.setNames("id", "fistName", "lastName", "birthday");
        //把解析出的一个数据映射为Customer对象
        DefaultLineMapper<Customer> mapper = new DefaultLineMapper<>();
        mapper.setLineTokenizer(tokenizer);
        mapper.setFieldSetMapper(new FieldSetMapper<Customer>() {
            /**
             * 映射
             */
            @Override
            public Customer mapFieldSet(FieldSet fieldSet) {
                Customer customer = new Customer();
                customer.setId(fieldSet.readLong("id"));
                customer.setFirstName(fieldSet.readString("fistName"));
                customer.setLastName(fieldSet.readString("lastName"));
                customer.setBirthday(fieldSet.readString("birthday"));
                return customer;
            }
        });
        mapper.afterPropertiesSet();
        customerFlatFileItemReader.setLineMapper(mapper);
    }

    @Override
    public Customer read() throws Exception {
        Customer customer;
        this.curLine++;

        if (restart) {
            customerFlatFileItemReader.setLinesToSkip(this.curLine.intValue() - 1);
            restart = false;
            System.out.println("Start reading from line: " + this.curLine);
        }
        customerFlatFileItemReader.open(this.executionContext);
        customer = customerFlatFileItemReader.read();
        if (customer != null && "WrongName".equals(customer.getFirstName())) {
            throw new RuntimeException("Something wrong. Customer id:" + customer.getId());
        }
        return customer;
    }

    @Override
    public void open(ExecutionContext executionContext) throws ItemStreamException {
        this.executionContext = executionContext;

        if (executionContext.containsKey("curLine")) {
            this.curLine = executionContext.getLong("curLine");
            this.restart = true;
        } else {
            this.curLine = 0L;
            executionContext.put("curLine", this.curLine);
            System.out.println("Start reading from line: " + this.curLine + 1);
        }
    }

    @Override
    public void update(ExecutionContext executionContext) throws ItemStreamException {
        executionContext.put("curLine", this.curLine);
        System.out.println("currentLine:" + this.curLine);
    }

    @Override
    public void close() throws ItemStreamException {

    }
}
